﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;

using Danser_AJAXEnabledWebApplication.User_Controls;
using Danser_AJAXEnabledWebApplication.User_Controls.GraphControl;
using Danser_AJAXEnabledWebApplication.Query_Popups;
using Danser_Control.Managers;
using Danser_Entity.Entities;
using Danser_Entity.Queries.Data;
using Danser_Entity.Queries.Filters;

namespace Danser_AJAXEnabledWebApplication.PageExt
{
    /// <summary>
    /// Abstract class representing test data display functionality
    /// </summary>
    public abstract class TestDataDisplay : AbstractPage
    {
        #region Members:

        protected IValidationManager _validationManager;

        protected int _additionalParamsSelected = 4;
        protected int _RXParamsSelected = 3;
        protected int _TXParamsSelected = 3;
        protected int _RSSIParamsSelected = 3;

        #endregion

        #region Constants:

        //session parameters
        protected const String SELECTED_TEST_ID = "selectedTestId";

        //Tests data object data source parameters
        protected const String ODS_FILTER_PARAMETER = "filter";

        protected const String DISPLAY_TEST_BUTTON_ID = "displayRowLinkButton";
        protected const String VALIDATION_STATUS_LABEL_ID = "validationStatusLabel";
        protected const String VALIDATIONS_TEXT_BOX_ID = "failedValidationsTextBox";

        //Test Results Table Header
        protected const String ADDITIONAL_INFO_HEADER = "Additional Information";
        protected const String RX_HEADER = "RX";
        protected const String TX_HEADER = "TX";
        protected const String RSSI_HEADER = "RSSI";

        //Pattern for columns template
        protected const String FIELD_PREFIX = "^";
        protected const String FIELD_SUFFIX = "$";

        protected const String COLUMNS_TEMPLATE =
            FIELD_PREFIX + "Name"               + FIELD_SUFFIX + "|" +
            FIELD_PREFIX + "Date"               + FIELD_SUFFIX + "|" +
            FIELD_PREFIX + "Status"             + FIELD_SUFFIX + "|" +
            FIELD_PREFIX + "Failed Validations" + FIELD_SUFFIX + "|" +
            FIELD_PREFIX + "Confirmed"          + FIELD_SUFFIX + "|" +
            FIELD_PREFIX + "Anchor"             + FIELD_SUFFIX;

        //for expression buldiers definitions
        protected readonly Groups[] TEST_INFO_SEARCH =
            new Groups[] 
            {
                Groups.Information
            };

        protected readonly Groups[] TEST_RESULTS_SEARCH =
            new Groups[]
            {
                Groups.Parameters, 
                Groups.Results
            };

        /// <summary>
        /// The display modes of the tests' data
        /// </summary>
        protected readonly String[] RESULTS_DISPLAY_MODE =
            new String[] 
            { 
                "Graph Display", 
                "Numeric Display" 
            };

        #endregion

        #region Page Load:

        /// <summary>
        /// loads the page...
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected override void Page_Load(object sender, EventArgs e)
        {
            base.Page_Load(sender, e);

            //for validation status issues
            _validationManager = ManagerFactory.ValidationManager();
        }

        #endregion

        #region View Handling:

        /// <summary>
        /// Toggle the results display modes for a selected test
        /// </summary>
        ///<param name="numericPanel">the page's numeric panel</param>
        ///<param name="graphicPanel">the page's graphic panel</param>
        ///<param name="viewButton">the button to switch view modes</param>
        ///<param name="graphControl">the page's graph control</param>
        public void ToggleView(Panel numericPanel, Panel graphicPanel, Button viewButton, GraphUserControl graphControl)
        {
            //cannot be visible together
            if (numericPanel.Visible != graphicPanel.Visible)
            {
                numericPanel.Visible = !numericPanel.Visible;
                graphicPanel.Visible = !graphicPanel.Visible;
            }

            //indicates for the desired display mode
            _pageFormatter.ToggleButtonText(viewButton, RESULTS_DISPLAY_MODE);

            //trigger the graph control
            if (graphicPanel.Visible)
            {
                try
                {
                    _pageFormatter.SetGraphInput(graphControl, (String)Session[SELECTED_TEST_ID]);
                }
                catch (Danser_Control.Exceptions.DanserGraphException graphException)
                {
                    HandleGenericErrorPage(graphException);
                }
            }

        }

        /// <summary>
        /// displays test results of a selected test
        /// </summary>
        /// <param name="testInfoIndex">the test id to display the results</param>
        /// <param name="dataSource">the data source to retrieve data</param>
        /// <param name="grid">the grid to display the selected data</param>
        public void GetTestResults(String testInfoIndex, ObjectDataSource dataSource, GridView grid)
        {
            RuleExpression expression = new RuleExpression();

            Condition condition =
                String.IsNullOrEmpty(testInfoIndex) ?
                // if no test selected, create an always false filter expression
                new FalseCondition() : 
                // if test selected, create the proper filter expression
                new Condition(
                    Groups.Information,
                    TestInfoFields.TestInfoIndex.ToString(),
                    ComparingOperators.EQUALS,
                    testInfoIndex.ToString(),
                    BooleanOperators.AND,
                    false);

            expression.Conditions.Add(condition);

            try
            {
                dataSource.SelectParameters[ODS_FILTER_PARAMETER].DefaultValue =
                    expression.ConditionsToString(true);

                grid.DataBind();
            }
            catch (Exception exception)
            {
                HandleGenericErrorPage(exception);
            }

        }

        /// <summary>
        /// Format the header line of the results grid
        /// </summary>
        /// <param name="sender">sent from event handler</param>
        /// <param name="e">sent from event handler</param>
        /// <param name="resultsGrid">the results grid with the header to format</param>
        protected void FormatResultsHeader(GridView resultsGrid)
        {
            //get parameters from session
            _additionalParamsSelected = Session[ADDITIONAL_INFO_HEADER]!=null ? (int)Session[ADDITIONAL_INFO_HEADER] : _additionalParamsSelected;
            _RXParamsSelected =         Session[RX_HEADER]!=null ? (int)Session[RX_HEADER] : _RXParamsSelected;
            _TXParamsSelected =         Session[TX_HEADER]!=null ? (int)Session[TX_HEADER] : _TXParamsSelected;
            _RSSIParamsSelected =       Session[RSSI_HEADER]!=null ? (int)Session[RSSI_HEADER] : _RSSIParamsSelected;

            //create the new header row
            GridViewRow HeaderGridRow =
                new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Insert);

            //cell variant used to create and add the header cells to header row
            TableCell HeaderCell = null;

            if (_additionalParamsSelected > 0)
            {
                HeaderCell = CreateTableCell(ADDITIONAL_INFO_HEADER, _additionalParamsSelected);
                HeaderGridRow.Cells.Add(HeaderCell);
            }

            if (_RXParamsSelected > 0)
            {
                HeaderCell = CreateTableCell(RX_HEADER, _RXParamsSelected);
                HeaderGridRow.Cells.Add(HeaderCell);
            }

            if (_TXParamsSelected > 0)
            {
                HeaderCell = CreateTableCell(TX_HEADER, _TXParamsSelected);
                HeaderGridRow.Cells.Add(HeaderCell);
            }

            if (_RSSIParamsSelected > 0)
            {
                HeaderCell = CreateTableCell(RSSI_HEADER, _RSSIParamsSelected);
                HeaderGridRow.Cells.Add(HeaderCell);
            }

            //add to main gridview the new header
            resultsGrid.Controls[0].Controls.AddAt(0, HeaderGridRow);

        }

        /// <summary>
        /// set the column span of eac header cell according to selected columns
        /// </summary>
        /// <param name="list"></param>
        protected void SetHeaderColumnSpan(MultiSelectList list)
        {
            int tmpAddParams = 0;
            int tmpRXParams = 0;
            int tmpTXParams = 0;
            int tmpRSSIParams = 0;
            for (int i = 0; i < list.Items.Count; i++)
            {
                //in case column is hidden, check which header is to be modified
                if (list.Items[i].Selected)
                {
                    if (i < 4)
                        tmpAddParams++;
                    else if (i < 7)
                        tmpRXParams++;
                    else if (i < 10)
                        tmpTXParams++;
                    else if (i < 13)
                        tmpRSSIParams++;
                }
            }

            //update session parameters
            Session[ADDITIONAL_INFO_HEADER] = _additionalParamsSelected = tmpAddParams;
            Session[RX_HEADER] = _RXParamsSelected = tmpRXParams;
            Session[TX_HEADER] = _TXParamsSelected = tmpTXParams;
            Session[RSSI_HEADER] = _RSSIParamsSelected = tmpRSSIParams;
        }

        /// <summary>
        /// Create a cell to add to a grid row
        /// </summary>
        /// <param name="caption">the text appears in the cell</param>
        /// <param name="columnspan">number of columns to span</param>
        protected TableCell CreateTableCell(String caption, int columnspan)
        {
            TableCell cell = new TableCell();
            cell.BorderColor = Color.Black;
            cell.Text = caption;
            cell.ColumnSpan = columnspan;

            return cell;
        }

        /// <summary>
        /// refresh graph display when selecting anchor tests
        /// </summary>
        /// <param name="graphControl">the graph control to refresh</param>
        public void RefreshAnchorsInGraph(GraphUserControl graphControl)
        {
            IList<String> testInfoIds = Session[SelectAnchors.SESSION_SELECTED_ANCHORS] as IList<String>;

            String currentTestId = Session[SELECTED_TEST_ID] as String;

            //send data to graph control
            _pageFormatter.SetGraphInput(graphControl, currentTestId, testInfoIds);
        }

        #endregion

        #region Data Handling:

        /// <summary>
        /// Common method to execute a query on a table 
        /// </summary>
        /// <param name="dataSource">object data source represents tab;e's data</param>
        /// <param name="builder">expression builder containing the query to execute</param>
        public void ExecuteSelect(ObjectDataSource dataSource, ExpressionBuilder builder)
        {
            ExecuteSelect(dataSource, builder, true);
        }

        public void ExecuteSelect(ObjectDataSource dataSource, ExpressionBuilder builder, bool validationEnabled)
        {
            //get the conditions generated by the expression builder
            IList<Condition> conditions = builder.getConditions(true, validationEnabled);

            if (conditions == null)
                return;

            //build a rule out of the conditions
            RuleExpression parsedRule = new RuleExpression(conditions);
            try
            {
                //when setting select parameter, SELECT method is automatically invoked
                dataSource.SelectParameters[ODS_FILTER_PARAMETER].DefaultValue =
                    parsedRule.ConditionsToString(true);
            }
            catch (Exception exception)
            {
                HandleGenericErrorPage(exception);
            }
        }

        /// <summary>
        /// Common method to handle table rows filter panel
        /// </summary>
        /// <param name="filterPanel">the panel</param>
        /// <param name="builder">the expression builder located on the panel</param>
        /// <param name="searchTables">tables to filter rows from</param>
        public void HandleFilterRowsPanel(Panel filterPanel, ExpressionBuilder builder, Groups[] searchTables)
        {
            filterPanel.Visible = !filterPanel.Visible;
            builder.setSearchingTables(searchTables);
            builder.setBuilderMode(BuilderModes.BUILD_QUERY);
        }

        #endregion
    }
}
